home *** CD-ROM | disk | FTP | other *** search
-
- // Matv - A Simple Matrix Class
-
- // Version: 1.0
- // Author: Mark Von Tress, Ph.D.
- // Date: 10/11/92
-
- // Copyright(c) Mark Von Tress 1992
-
-
- // DISCLAIMER: THIS PROGRAM IS PROVIDED AS IS, WITHOUT ANY
- // WARRANTY, EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED
- // TO FITNESS FOR A PARTICULAR PURPOSE. THE AUTHOR DISCLAIMS
- // ALL LIABILITY FOR DIRECT OR CONSEQUENTIAL DAMAGES RESULTING
- // FROM USE OF THIS PROGRAM.
-
-
- #include "matv.h"
-
- //////////////////////////////// vector
-
- ///// error handler
- FLOAT Vector::Nrerror(const char *errormsg)
- {
- FLOAT x = 2;
- cout << "\nMATRIX ERROR: " << errormsg << "\nexiting to system\n";
- cerr << "\nMATRIX ERROR: " << errormsg << "\nexiting to system\n";
- x = 2;
- exit(1);
- return x;
- }
-
- ///// Matrix integrity
- void Vector::Garbage(const char *errormsg)
- {
- int errorint = 0;
- if (signature != SIGNATURE) errorint++;
- if (n <= 0) errorint++;
- if (c[-1] != signature) errorint++;
- if (errorint) {
- cout << "Operating on a Corrupted matrix: " << "\n";
- Nrerror(errormsg);
- }
- }
-
- ///// index
- FLOAT &Vector::operator () (int i)
- {
- return c[i];
- }
-
- ///// output
- ostream &operator << (ostream &s, Vector &v)
- {
- #ifndef NO_CHECKING
- v.Garbage("Vector <<: v is garbage");
- #endif
- s << "CanDelete: " << (int) v.CanDelete << " CanAlias: "
- << (int) v.CanAlias << " c:\t" << v.c << "\n";
- for (int i = 0; i < v.n; i++) {
- s << v(i) << " ";
- if (!(i % 7) && i > 0) s << "\n";
- }
- s << "\n";
- return s;
- }
-
- ///// memory allocator
- FLOAT *Vector::SetupVectors(int nn)
- {
- static unsigned long myconst =
- (65536 / ((unsigned long) sizeof (FLOAT))) - 2;
-
- if (nn <= 0) Nrerror("SetupVectors: n < 0");
- if (nn > myconst)
- Nrerror("SetupVectors: more than 64K in vector(n>16382)");
-
- n = nn;
- c = new FLOAT[n + 1];
- if (!c) Nrerror("SetupVectors: allocation error");
- c[0] = signature = SIGNATURE;
- c++;
- c[0] = 1;
- return c;
- }
-
- ///// memory deletion
- void Vector::PurgeVectors(void)
- {
- signature++;
- if (*-- c == SIGNATURE) {
- c[0] = 0;
- delete[] c;
- }
- else
- Vector::Nrerror("PurgeVectors: attempting to delete a deleted vector");
- }
-
- ////////// constructors
- ///// default constructor
- Vector::Vector(void) : n(1), CanDelete(TTRUE), CanAlias(TTRUE),
- signature(SIGNATURE)
- {
- c = SetupVectors(1);
- }
-
- ///// allocate an n vector
- Vector::Vector(int nn) : n(nn), CanDelete(TTRUE), CanAlias(TTRUE),
- signature(SIGNATURE)
- {
- c = SetupVectors(nn);
- }
-
- ///// copy an array into a vector
- Vector::Vector(int nn, FLOAT *x) : n(nn), CanDelete(TTRUE),
- CanAlias(TTRUE), signature(SIGNATURE)
- {
- c = SetupVectors(nn);
- FLOAT *cc = c;
- FLOAT *acc = x;
- int i = n;
- while (i--) *cc++ = *acc++;
- }
-
- ///// copy constructor
- Vector::Vector(Vector &a) : n(a.n), CanDelete(TTRUE), CanAlias(TTRUE),
- signature(SIGNATURE)
- {
- if (a.CanDelete == FFALSE && a.CanAlias) {
- // a is not responsible for deleting c and a can have an alias
- c = a.c;
- }
- else {
- c = SetupVectors(a.n);
- FLOAT *cc = c;
- FLOAT *acc = a.c;
- int i = n;
- while (i--) *cc++ = *acc++;
- }
- }
-
- ///// destructor
- Vector::~Vector()
- {
- n = 0;
- if (CanDelete == TTRUE)
- PurgeVectors();
- }
-
- ////// assignment
- Vector &Vector::operator = (Vector &a)
- {
- #ifndef NO_CHECKING
- a.Garbage("Vector Assignment: a is garbage");
- Garbage("Vector Assignment: *this is garbage");
- #endif
- if (this == &a) return *this;
- // deal with aliased storage
- if (c == a.c && a.CanDelete == FFALSE) {
- // *this is aliased with a, and a is not
- // responsible for deleting c.
- CanDelete = TTRUE;
- n = a.n;
- return *this;
- }
- if (c == a.c && a.CanDelete == TTRUE) {
- // *this is aliased with a, and a is
- // responsible for deleting c.
- c = SetupVectors(a.n);
- CanDelete = TTRUE;
- }
- // *this is no longer aliased with a
- if (n != a.n) {
- PurgeVectors();
- c = SetupVectors(a.n);
- }
- FLOAT *cc = c;
- FLOAT *acc = a.c;
- int i = n;
- while (i--) *cc++ = *acc++;
- return *this;
- }
-
- //////////////////////// matrix class
-
- ///// indexing
- FLOAT &Matrix::operator () (int i, int j) {
- #ifndef NO_CHECKING
- if (i < 1 || i > r || j < 1 || j > c)
- Nrerror("operator(): index out of range");
- #endif
- return Vector::operator () ((i - 1) *c + (j - 1));
- }
-
- ///// assignment
- Matrix &Matrix::operator = (Matrix &a)
- {
- #ifndef NO_CHECKING
- a.Garbage("Matrix Assignment: a is garbage");
- Garbage("Matrix Assignment: *this is garbage");
- #endif
- r = a.r;
- c = a.c;
- this->Vector::operator = (a);
- return *this;
- }
-
- ///// output
- ostream &operator << (ostream &s, Matrix &m)
- {
- #ifndef NO_CHECKING
- m.Garbage("<<: m is garbage");
- #endif
- s << "\n";
- for (int i = 1; i <= m.r; i++) {
- for (int j = 1; j <= m.c; j++)
- s << m(i, j) << " ";
- s << "\n";
- }
- s << "\n";
- return s;
- }
-
- void Matrix::show(char *str)
- {
- #ifndef NO_CHECKING
- Garbage("show: *this is garbage");
- #endif
- cout << str << "\n";
- cout << *this;
- }
-
- //////////// matrix operators
-
- ///// addition
- Matrix operator + (Matrix &a, Matrix &b)
- {
- #ifndef NO_CHECKING
- a.Garbage("Matrix +: a is garbage");
- b.Garbage("Matrix +: b is garbage");
- #endif
- if (a.r != b.r || a.c != b.c)
- a.Nrerror("matrices do not conform in addition");
-
- Matrix c(a.r, a.c);
- for (int i = 1; i <= c.r; i++)
- for (int j = 1; j <= c.c; j++) c(i, j) = a(i, j) + b(i, j);
- c.release();
- return c;
- }
-
- Matrix operator + (Matrix &a, FLOAT b)
- {
- #ifndef NO_CHECKING
- a.Garbage("Matrix +: a is garbage");
- #endif
-
- Matrix c(a.r, a.c);
- for (int i = 1; i <= c.r; i++)
- for (int j = 1; j <= c.c; j++) c(i, j) = a(i, j) + b;
- c.release();
- return c;
- }
-
- Matrix operator + (FLOAT b, Matrix &a)
- {
- #ifndef NO_CHECKING
- a.Garbage("Matrix +: a is garbage");
- #endif
-
- Matrix c(a.r, a.c);
- for (int i = 1; i <= c.r; i++)
- for (int j = 1; j <= c.c; j++) c(i, j) = a(i, j) + b;
- c.release();
- return c;
- }
-
- Matrix &Matrix::operator += (Matrix &a)
- {
- #ifndef NO_CHECKING
- a.Garbage("Matrix +=: a is garbage");
- Garbage("Matrix +=: *this is garbage");
- #endif
- if (a.r != r || a.c != c)
- a.Nrerror("matrices do not conform in addition");
-
- for (int i = 1; i <= r; i++)
- for (int j = 1; j <= c; j++) (*this)(i, j) += a(i,j);
-
- return *this;
- }
-
- Matrix &Matrix::operator += (FLOAT b)
- {
- #ifndef NO_CHECKING
- Garbage("Matrix +=: *this is garbage");
- #endif
-
- for (int i = 1; i <= r; i++)
- for (int j = 1; j <= c; j++) (*this)(i, j) += b;
-
- return *this;
- }
-
- ///// subtraction
- Matrix operator - (Matrix &a, Matrix &b)
- {
- #ifndef NO_CHECKING
- a.Garbage("Matrix -: a is garbage");
- b.Garbage("Matrix -: b is garbage");
- #endif
- if (a.r != b.r || a.c != b.c)
- a.Nrerror("matrices do not conform in subtraction");
-
- Matrix c(a.r, a.c);
- for (int i = 1; i <= c.r; i++)
- for (int j = 1; j <= c.c; j++) c(i, j) = a(i, j) - b(i, j);
- c.release();
- return c;
- }
-
- Matrix operator - (Matrix &a, FLOAT b)
- {
- #ifndef NO_CHECKING
- a.Garbage("Matrix -: a is garbage");
- #endif
-
- Matrix c(a.r, a.c);
- for (int i = 1; i <= c.r; i++)
- for (int j = 1; j <= c.c; j++) c(i, j) = a(i, j) - b;
- c.release();
- return c;
- }
-
- Matrix operator - (FLOAT b, Matrix &a)
- {
- #ifndef NO_CHECKING
- a.Garbage("Matrix -: a is garbage");
- #endif
-
- Matrix c(a.r, a.c);
- for (int i = 1; i <= c.r; i++)
- for (int j = 1; j <= c.c; j++) c(i, j) = b - a(i, j);
- c.release();
- return c;
- }
-
- Matrix operator - (Matrix &a)
- {
- #ifndef NO_CHECKING
- a.Garbage("Matrix Unary -: a is garbage");
- #endif
- Matrix c(a.r, a.c);
- for (int i = 1; i <= c.r; i++)
- for (int j = 1; j <= c.c; j++) c(i, j) = -a(i, j);
- c.release();
- return c;
- }
-
- Matrix &Matrix::operator -= (Matrix &a)
- {
- #ifndef NO_CHECKING
- a.Garbage("Matrix -=: a is garbage");
- Garbage("Matrix -=: *this is garbage");
- #endif
- if (a.r != r || a.c != c)
- a.Nrerror("matrices do not conform in subtraction");
-
- for (int i = 1; i <= r; i++)
- for (int j = 1; j <= c; j++) (*this)(i, j) -= a(i,j);
-
- return *this;
- }
-
- Matrix &Matrix::operator -= (FLOAT b)
- {
- #ifndef NO_CHECKING
- Garbage("Matrix -=: *this is garbage");
- #endif
-
- for (int i = 1; i <= r; i++)
- for (int j = 1; j <= c; j++) (*this)(i, j) -= b;
-
- return *this;
- }
-
- ///// multiplication
- Matrix operator *(Matrix &a, Matrix &b)
- {
- #ifndef NO_CHECKING
- a.Garbage("Matrix *: a is garbage");
- b.Garbage("Matrix *: b is garbage");
- #endif
- if (a.c != b.r)
- a.Nrerror("matrices do not conform in multiplication");
-
- Matrix c(a.r, b.c);
- LFLOAT sum;
- for (int i = 1; i <= a.r; i++)
- for (int j = 1; j <= b.c; j++) {
- sum = 0;
- for (int k = 1; k <= a.c; k++)
- sum += (LFLOAT) ((LFLOAT) a(i, k)) *((LFLOAT) b(k, j));
- c(i, j) =(FLOAT) sum;
- }
- c.release();
- return c;
- }
-
- Matrix operator *(Matrix &a, FLOAT b)
- {
- #ifndef NO_CHECKING
- a.Garbage("Matrix *: a is garbage");
- #endif
-
- Matrix c(a.r, a.c);
- for (int i = 1; i <= c.r; i++)
- for (int j = 1; j <= c.c; j++) c(i, j) = a(i, j) *b;
- c.release();
- return c;
- }
-
- Matrix operator *(FLOAT b, Matrix &a)
- {
- #ifndef NO_CHECKING
- a.Garbage("Matrix *: a is garbage");
- #endif
-
- Matrix c(a.r, a.c);
- for (int i = 1; i <= c.r; i++)
- for (int j = 1; j <= c.c; j++) c(i, j) = a(i, j) *b;
- c.release();
- return c;
- }
-
- Matrix &Matrix::operator *= (Matrix &a)
- {
- #ifndef NO_CHECKING
- a.Garbage("Matrix *=: a is garbage");
- Garbage("Matrix *=: *this is garbage");
- #endif
- if (a.r != c)
- a.Nrerror("matrices do not conform in multiplication");
-
- LFLOAT sum = 0;
- Matrix cc( r, a.c );
- for (int i = 1; i <= cc.r; i++)
- for (int j = 1; j <= cc.c; j++){
- sum = 0;
- for( int k=1; k<=c; k++)
- sum += (LFLOAT) ((LFLOAT) (*this)(i, k)) *((LFLOAT) a(k, j));
- cc(i, j) = (FLOAT) sum;
- }
- *this = cc;
- return *this;
- }
-
- Matrix &Matrix::operator *= (FLOAT b)
- {
- #ifndef NO_CHECKING
- Garbage("Matrix *=: *this is garbage");
- #endif
-
- for (int i = 1; i <= r; i++)
- for (int j = 1; j <= c; j++) (*this)(i, j) *= b;
-
- return *this;
- }
-
- //////////////// elementwise multiplication
- Matrix operator % (Matrix &a, Matrix &b)
- {
- #ifndef NO_CHECKING
- a.Garbage("Matrix %: a is garbage");
- b.Garbage("Matrix %: b is garbage");
- #endif
-
- if (a.r != b.r || a.c != b.c)
- a.Nrerror("matrices do not conform in elementary multiplication");
-
- Matrix c(a.r, a.c);
- for (int i = 1; i <= c.r; i++)
- for (int j = 1; j <= c.c; j++) c(i, j) = a(i, j) *b(i, j);
- c.release();
- return c;
- }
-
- Matrix operator % (Matrix &a, FLOAT b)
- {
- #ifndef NO_CHECKING
- a.Garbage("Matrix %: a is garbage");
- #endif
-
- Matrix c(a.r, a.c);
- for (int i = 1; i <= c.r; i++)
- for (int j = 1; j <= c.c; j++) c(i, j) = a(i, j) *b;
- c.release();
- return c;
- }
-
- Matrix operator % (FLOAT b, Matrix &a)
- {
- #ifndef NO_CHECKING
- a.Garbage("Matrix %: a is garbage");
- #endif
-
- Matrix c(a.r, a.c);
- for (int i = 1; i <= c.r; i++)
- for (int j = 1; j <= c.c; j++) c(i, j) = a(i, j) *b;
- c.release();
- return c;
- }
-
- Matrix &Matrix::operator %= (Matrix &a)
- {
- #ifndef NO_CHECKING
- a.Garbage("Matrix %=: a is garbage");
- Garbage("Matrix %=: *this is garbage");
- #endif
- if (a.r != r || a.c != c)
- a.Nrerror("matrices do not conform in elementwise multiplication");
-
- for (int i = 1; i <= r; i++)
- for (int j = 1; j <= c; j++) (*this)(i, j) *= a(i,j);
-
- return *this;
- }
-
- Matrix &Matrix::operator %= (FLOAT b)
- {
- #ifndef NO_CHECKING
- Garbage("Matrix %=: *this is garbage");
- #endif
-
- for (int i = 1; i <= r; i++)
- for (int j = 1; j <= c; j++) (*this)(i, j) *= b;
-
- return *this;
- }
-
- ///// elementwise division
- Matrix operator / (Matrix &a, Matrix &b)
- {
- #ifndef NO_CHECKING
- a.Garbage("Matrix /: a is garbage");
- b.Garbage("Matrix /: b is garbage");
- #endif
-
- if (a.r != b.r || a.c != b.c)
- a.Nrerror("matrices do not conform in division");
-
- Matrix c(a.r, a.c);
- for (int i = 1; i <= c.r; i++)
- for (int j = 1; j <= c.c; j++)
- if (b(i, j)) c(i, j) = a(i, j) / b(i, j);
- else b.Nrerror("zero divisor in elementwise division");
- c.release();
- return c;
- }
-
- Matrix operator / (Matrix &a, FLOAT b)
- {
- #ifndef NO_CHECKING
- a.Garbage("Matrix /: a is garbage");
- #endif
-
- if (b == 0.0) a.Nrerror("Matrix /: b is zero");
-
- Matrix c(a.r, a.c);
- for (int i = 1; i <= c.r; i++)
- for (int j = 1; j <= c.c; j++)
- c(i, j) = a(i, j) / b;
- c.release();
- return c;
- }
-
- Matrix operator / (FLOAT b, Matrix &a)
- {
- #ifndef NO_CHECKING
- a.Garbage("Matrix /: a is garbage");
- #endif
-
- Matrix c(a.r, a.c);
- for (int i = 1; i <= c.r; i++)
- for (int j = 1; j <= c.c; j++)
- if (a(i, j)) c(i, j) = b / a(i, j);
- else
- a.Nrerror("zero divisor in elementwise division");
- c.release();
- return c;
- }
-
- Matrix &Matrix::operator /= (Matrix &a)
- {
- #ifndef NO_CHECKING
- a.Garbage("Matrix /=: a is garbage");
- Garbage("Matrix /=: *this is garbage");
- #endif
- if (a.r != r || a.c != c)
- a.Nrerror("matrices do not conform in elementwise division");
-
- for (int i = 1; i <= r; i++)
- for (int j = 1; j <= c; j++)
- (*this)(i, j) /= ( a(i,j) ) ? a(i,j) :
- Nrerror("zero divisor in elementwise division");
-
- return *this;
- }
-
- Matrix &Matrix::operator /= (FLOAT b)
- {
- #ifndef NO_CHECKING
- Garbage("Matrix /=: *this is garbage");
- #endif
- if (!b) Nrerror("zero divisor in elementwise division");
-
- for (int i = 1; i <= r; i++)
- for (int j = 1; j <= c; j++) (*this)(i, j) /= b;
-
- return *this;
- }
-
- /////////////////// matrix functions
-
- //// sweep out rows k1 through k2, operates on "a"
- Matrix Sweep(int k1, int k2, Matrix& a)
- {
- #ifndef NO_CHECKING
- a.Garbage("Sweep: a is garbage");
- #endif
-
- LFLOAT eps = 1.0e-8, d;
- int i, j, k, n, it;
-
- if (a.c != a.r)
- a.Nrerror("sweep: matrix a not square");
-
- n = a.r;
- if (k2 < k1) { k = k1; k1 = k2; k2 = k; }
-
- for (k = k1; k <= k2; k++) {
- if (fabs(a(k, k)) < eps)
- for (it = 1; it <= n; it++)
- a(it, k) = a(k, it) = 0;
- else {
- d = 1.0 / a(k, k);
- a(k, k) = d;
- for (i = 1; i <= n; i++) { if (i != k)
- a(i, k) = a(i, k) *(LFLOAT) - d; }
- for (j = 1; j <= n; j++) { if (j != k)
- a(k, j) = a(k, j) *(LFLOAT) d; }
- for (i = 1; i <= n; i++) {
- if (i != k) {
- for (j = 1; j <= n; j++) {
- if (j != k)
- a(i, j) = a(i, j) + a(i, k) *a(k, j) / d;
- } // end for j
- } // end for i != k
- } // end for i
- } // end else
- } // end for k
- return a;
- } /*sweep*/
-
- ///// inversion
- Matrix Inv(Matrix &a)
- {
- #ifndef NO_CHECKING
- a.Garbage("Inv: a is garbage");
- #endif
-
- if (a.c != a.r)
- a.Nrerror("INVERSE: matrix a not square");
-
- Matrix b(a.r, a.c);
- b = a;
- Sweep(1, b.r, b);
- b.release();
- return b;
-
- } /* inverse */
-
-
- ///////////////////////// functions
-
- /////// transpose
- Matrix Tran(Matrix &a)
- {
- #ifndef NO_CHECKING
- a.Garbage("Tran: a is garbage");
- #endif
-
- Matrix c(a.c, a.r);
- for (int i = 1; i <= c.r; i++)
- for (int j = 1; j <= c.c; j++) c(i, j) = a(j, i);
- c.release();
- return c;
- }
-
-
- ////// fill with a constant
- Matrix Fill(int r, int cc, FLOAT d)
- {
- if (r < 1 || cc < 1) {
- Matrix exitnow;
- exitnow.Nrerror("invalid indices in Fill");
- }
-
- Matrix c(r, cc);
- for (int i = 1; i <= r; i++)
- for (int j = 1; j <= cc; j++) c(i, j) = d;
- c.release();
- return c;
- }
-
- //////// identity
- Matrix Ident(int n)
- {
- if (n < 1) {
- Matrix exitnow;
- exitnow.Nrerror("n < 1 in identity matrix");
- }
- Matrix c(n, n);
- for (int i = 1; i <= c.r; i++)
- for (int j = 1; j <= c.c; j++) c(i, j) = (i == j) ? 1 : 0;
- c.release();
- return c;
- }
-
- /////// extract a submatrix
- Matrix Submat(Matrix &a, int lr, int lc, int r, int c)
- {
- #ifndef NO_CHECKING
- a.Garbage("Submat: a is garbage");
- #endif
- if ((r > a.r) || (c > a.c)) {
- Matrix exitnow;
- exitnow.Nrerror("SUBMAT: index out of range");
- }
- int r2 = r - lr + 1;
- int c2 = c - lc + 1;
- Matrix b( r2, c2);
- int lrm1 = lr - 1;
- int lcm1 = lc - 1;
- for (int i = 1; i <= r2; i++) {
- for (int j = 1; j <= c2; j++) b(i, j) = a(lrm1 + i, lcm1 + j);
- }
- b.release();
- return b;
- } /* submat */
-
- ///// horizontal concatination
- Matrix Ch(Matrix &a, Matrix &b)
- {
- #ifndef NO_CHECKING
- a.Garbage("Ch");
- b.Garbage("Ch");
- #endif
-
- if (a.r != b.r)
- a.Nrerror("CH: matrices have different number of rows");
-
- Matrix c(a.r, a.c+b.c);
-
- for (int i = 1; i <= a.r; i++) {
- for (int j = 1; j <= a.c; j++)
- c(i, j) = a(i, j);
- }
- int ii;
- for (i = 1, ii = 1; i <= b.r; i++, ii++) {
- for (int j = 1, jj = 1; j <= b.c; j++, jj++)
- c(ii, jj + a.c) = b(i, j);
- }
- c.release();
- return c;
- } /* ch */
-
- ///// vertical concatination
- Matrix Cv(Matrix &a, Matrix &b)
- {
- #ifndef NO_CHECKING
- a.Garbage("Cv");
- b.Garbage("Cv");
- #endif
-
- if (a.c != b.c)
- a.Nrerror("CV: matrices have different number of columns");
-
- Matrix c( a.r+b.r, a.c);
-
- for (int i = 1; i <= a.r; i++) {
- for (int j = 1; j <= a.c; j++)
- c(i, j) = a(i, j);
- }
- int ii;
- for (i = 1, ii = 1; i <= b.r; i++, ii++) {
- for (int j = 1, jj = 1; j <= b.c; j++, jj++)
- c(ii + a.r, jj) = b(i, j);
- }
- c.release();
- return c;
- } /* cv */
-
- /////////////// io
-
- //////// read a matrix
- Matrix Reada(char *filename)
- {
- ifstream fp(filename);
- int i, j, r, c;
- char s[241];
- FLOAT f;
-
- if (!fp) {
- cerr << "Cannot open " << filename << ".\n";
- Matrix exitnow;
- exitnow.Nrerror("ReadA: file open failure");
- }
- fp.getline(s, 240, '\n');
- fp >> r >> c;
- Matrix a(r, c);
- for (i = 1; i <= r; i++) {
- for (j = 1; j <= c; j++)
- if (fp >> f) a(i, j) = f;
- else a.Nrerror("Reada: error reading input");
- }
- fp.close();
- a.release();
- return a;
- }
-
- /////////// write a matrix
- void Writea(char *filename, Matrix &a, const char *filetitle)
- {
- #ifndef NO_CHECKING
- a.Garbage("Writea: a is garbage");
- #endif
- ofstream fp(filename);
- int i, j;
-
- if (!fp) {
- cerr << "Cannot open " << filename << ".\n";
- a.Nrerror("Writea: file read failure");
- }
- fp << filetitle << "\n";
- fp << a.r << " " << a.c << "\n";
- for (i = 1; i <= a.r; i++) {
- for (j = 1; j <= a.c; j++)
- if (!(fp << a(i, j) << " "))
- a.Nrerror("error writing output");
- fp << "\n";
- }
- fp.close();
- }
-
-